﻿using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;

public class SystemPathFinding : MonoBehaviour
{

    private List<UnitPlot> openList = new List<UnitPlot>();
    private List<UnitPlot> closedList = new List<UnitPlot>();

    public List<UnitPlot> FindPath(UnitPlot startNode, UnitPlot goalNode)
    {
        openList = new List<UnitPlot>();
        closedList = new List<UnitPlot>();
        openList.Add(startNode);
        while (openList.Count > 0)
        {
            UnitPlot currentNode = GetLowestFCostNode(openList);
            if (currentNode == goalNode)
            {
                List<UnitPlot> path = GeneratePath(startNode, goalNode);
                //VisualizePath(path);
                return path;
            }
            openList.Remove(currentNode);
            closedList.Add(currentNode);
            foreach (UnitPlot neighbor in GetNeighbors(currentNode, goalNode))
            {
                if (closedList.Contains(neighbor) || (neighbor.isOccupy && neighbor != goalNode))
                    continue;
                int newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
                if (newMovementCostToNeighbor < neighbor.gCost || !openList.Contains(neighbor))
                {
                    neighbor.gCost = newMovementCostToNeighbor;
                    neighbor.hCost = GetDistance(neighbor, goalNode);
                    neighbor.parent = currentNode;
                    if (!openList.Contains(neighbor))
                        openList.Add(neighbor);
                }
            }
        }
        // No path found
        Debug.Log("Path not found!");
        return null;
    }

    private List<UnitPlot> GetNeighbors(UnitPlot node, UnitPlot goalNode)
    {
        List<UnitPlot> neighbors = new List<UnitPlot>();
        if (node.X > 0)
            neighbors.Add(FacilityController.Instance.dicPlots[node.X - 1][node.Z].GetComponent<UnitPlot>());
        if (node.X < FacilityController.Instance.dicPlots.Count - 1)
            neighbors.Add(FacilityController.Instance.dicPlots[node.X + 1][node.Z].GetComponent<UnitPlot>());
        if (node.Z > 0)
            neighbors.Add(FacilityController.Instance.dicPlots[node.X][node.Z - 1].GetComponent<UnitPlot>());
        if (node.Z < FacilityController.Instance.dicPlots[0].Count - 1)
            neighbors.Add(FacilityController.Instance.dicPlots[node.X][node.Z + 1].GetComponent<UnitPlot>());
        return neighbors;
    }

    private int GetDistance(UnitPlot nodeA, UnitPlot nodeB)
    {
        return Mathf.Abs(nodeA.X - nodeB.X) + Mathf.Abs(nodeA.Z - nodeB.Z);
    }

    private UnitPlot GetLowestFCostNode(List<UnitPlot> nodeList)
    {
        UnitPlot lowestFCostNode = nodeList[0];
        for (int i = 1; i < nodeList.Count; i++)
        {
            if (nodeList[i].fCost < lowestFCostNode.fCost)
                lowestFCostNode = nodeList[i];
        }
        return lowestFCostNode;
    }

    private List<UnitPlot> GeneratePath(UnitPlot startNode, UnitPlot goalNode)
    {
        List<UnitPlot> path = new List<UnitPlot>();
        UnitPlot currentNode = goalNode;
        while (currentNode != startNode)
        {
            path.Add(currentNode);
            currentNode = currentNode.parent;
        }
        path.Reverse();
        return path;
    }

    public void VisualizePath(List<UnitPlot> path)
    {
        foreach (UnitPlot node in path)
        {
            // Implement how to visualize the path in your scene
            // For example, change the color of the node or place a marker
            Debug.Log("Node: " + node.X + " " + node.Z);
        }
    }
}